module.exports = function(app) {
  return new Handler(app);
};

var Handler = function(app) {
  	this.app = app;
	this.statusService = this.app.get('statusService');
    this.closedFunc = onUserLeave.bind(null, app);
};

/**
 *  register user
 */
var common = require('../../../util/common');
var Fiber = require('fibers');
var util = require('util');
Handler.prototype.register = function(msg, session, next) {
    var app = this.app;
    var db = app.get('db');

    db.asyncGetConnection(function(err, conn) {
        if (err) {
            console.error(util.inspect(err));
            closeSession(app, session.id);
            throw new Error('mysql get connection failed!');
        } else {
            db.asyncQuery(conn, "SELECT id FROM `demo_user` WHERE name = ?", [msg.name], function(err, rows) {
                if (rows.length === 0) {
                    db.asyncQuery(conn, "INSERT INTO `demo_user`(`name`, `passwd`) VALUES (?, ?) ", [msg.name, msg.passwd], function(err) {
                    });
                    next(null, {code: 200, msg: '注册成功!'});
                } else {
                    next(null, {code: 500, msg: '用户名已存在'});
                }

                conn.release();
            });
        }
    });
};

/**
 * New client login.
 *
 * @param  {Object}   msg     request message
 * @param  {Object}   session current session object
 * @param  {Function} next    next step callback
 * @return {Void}
 */
var Player = require('../../../model/player');

Handler.prototype.login = function(msg, session, next) {
	var sid = this.app.getServerId();
	var globalChannelService = this.app.get('globalChannelService');
	var app = this.app;
    var statusService = this.statusService;
    var db = app.get('db');
    var cachedb = app.get('cachedb');
    var closedFunc = this.closedFunc;

    db.asyncGetConnection(function(err, conn) {
        if (err) {
            closeSession(app, session.id);
            throw new Error('get connection filed');
        } else {
            db.asyncQuery(conn, "SELECT id FROM `demo_user` WHERE name = ? and passwd = ?", [msg.name, msg.passwd], function (err, rows) {
                if (err) throw new Error('select login failed');
                if (rows.length === 0) {
                    next(null, {
                        code: 500,
                        msg: '用户名密码错误'
                    });
                } else {
                    var row = rows[0];
                    statusService.getSidsByUid(row.id, function(err, list) {
                        if (err) throw new Error('pomelo status plugin called getSidsByUid failed!');
                        // duplicate log in
                        if (list.length > 0) {
                            next(null, {
                                code: 500,
                                msg: '玩家已经登录'
                            });
                            return;
                        } else {
                            var uid = Number(row.id);
                            session.bind(uid);
                            sessionOn(session, 'closed', closedFunc);

                            // 将玩家添加进全局channel
                            globalChannelService.add("global_users", uid, sid);

                            // 将玩家添加进cachedb
                            var player = Player({
                                uid: uid,
                                name: msg.name,
                                sid: session.frontendId
                            });
                            cachedb.asyncSet(player.uid, JSON.stringify(player));

                            // 将玩家添加进场景
                            app.rpc.scene.remoteHandler.join(0, player, null);

                            next(null, {code: 200, msg: '登录成功'});
                        }
                    });
                }

                conn.release();
            });
        }
    });
};




/**
 * Notify 全局广播
 */
Handler.prototype.global_broadcast = function(msg, session) {
    var globalChannelService = this.app.get('globalChannelService');
    var cachedb = this.app.get('cachedb');
    cachedb.asyncGet(session.uid, function (err, data) {
        if (err) throw new Error('asyncGet redis failed!');
        var player = JSON.parse(data);
        globalChannelService.pushMessage('connector', 'onChat', {type: 1, msg: player.name + ': ' + msg.msg}, "global_users", null, function(err) {
            if (err) throw new Error('globalChannelService pushMessage failed!');
        });
    });
};

/**
 * 私聊
 */
Handler.prototype.private_chat = function(msg, session, next) {
    if (session.uid === msg.uid) {
        next(null, {
            code: 500,
            msg: '不能给自己发消息'
        });
        return;
    }
    var statusService = this.statusService;
    var cachedb = this.app.get('cachedb');
    statusService.getSidsByUid(msg.uid, function(err, list) {
        if (err) throw new Error('pomelo status plugin called getSidsByUid failed!');
        // duplicate log in
        if (list.length === 0) {
            next(null, {
                code: 200,
                msg: '玩家不在线'
            });
            return;
        } else {
            cachedb.asyncGet(session.uid, function (err, data) {
                if (err) throw new Error('asyncGet redis failed!');
                var player = JSON.parse(data);
                statusService.pushByUids([msg.uid], 'onChat', {type: 3, msg: player.name + ': ' + msg.msg}, function(err) {
                    if (err) throw new Error('statusService pushByUids failed!');
                });
                next(null, {
                    code: 200,
                    msg: '私聊发送成功'
                });
            });
        }
    });
};

/**
 * logout
 */
Handler.prototype.logout = function (msg, session, next) {
    if (!session || !session.uid) {
        next(null, {code: 500, msg: '未登录'});
    } else {
        var globalChannelService = this.app.get('globalChannelService');
        globalChannelService.leave("global_users", session.uid, session.frontendId);

        // 离开场景
        this.app.rpc.scene.remoteHandler.leave(session.get('scene'), session.uid, session.frontendId, null);

        // 从cachedb中删除玩家
        var cachedb = this.app.get('cachedb');
        cachedb.asyncDel(session.uid);

        next(null, {code: 200, msg: '退出成功'});

        sessionRemoveListener(session, 'closed', this.closedFunc);
        closeSession(this.app, session.id);
    }
};

/**
 * User log out handler
 */
var onUserLeave = function(app, session) {
	if (!session || !session.uid) {
		return;
	}

	var globalChannelService = app.get('globalChannelService');
	globalChannelService.leave("global_users", session.uid, session.frontendId);

	// 离开场景
	app.rpc.scene.remoteHandler.leave(session.get('scene'), session.uid, session.frontendId, null);

    // 从cachedb中删除玩家
    var cachedb = app.get('cachedb');
    cachedb.asyncDel(session.uid);
};


/**
 * 关闭session
 * @param app
 * @param id
 */
function closeSession(app, id) {
    var sessionService = app.get('sessionService');
    sessionService.kickBySessionId(id);
}

/**
 * 给session注册事件监听器的时候最好用这种方法
 * @param session
 * @param event
 * @param listener
 */
function sessionOn(session, event, listener) {
    session.__session__.on(event, listener);
}

/**
 * 删除seesion上注册的事件监听器必须用这种方法，不能直接用session.remove*系列的函数
 * 并且不能对__session__调用removeAllListener()方法，因为pomelo内部要需要通过事件监听器对session进行清理工作
 * @param session
 * @param event
 * @param listener
 */
function sessionRemoveListener(session, event, listener) {
    session.__session__.removeListener(event, listener);
}